package com.opendeepsearch.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Objects;

public class Configuration {
    private static final Logger logger = LoggerFactory.getLogger(Configuration.class);
    
    private String summarizationModel;
    private String researchModel;
    private String compressionModel;
    private String finalReportModel;
    private String searchApi;
    private int maxStructuredOutputRetries;
    private boolean allowClarification;
    private int maxConcurrentResearchUnits;
    private int maxResearcherIterations;
    private int maxReactToolCalls;
    private List<String> availableTools;
    private String mcpServerUrl;
    private boolean mcpRequireAuth;

    public Configuration(String summarizationModel, String researchModel, String compressionModel,
                         String finalReportModel, String searchApi, int maxStructuredOutputRetries,
                         boolean allowClarification, int maxConcurrentResearchUnits, int maxResearcherIterations,
                         int maxReactToolCalls, List<String> availableTools, String mcpServerUrl,
                         boolean mcpRequireAuth) {
        
        validateConfiguration(summarizationModel, researchModel, compressionModel, finalReportModel, 
                            searchApi, maxStructuredOutputRetries, maxConcurrentResearchUnits, 
                            maxResearcherIterations, maxReactToolCalls, availableTools, mcpServerUrl);
        
        this.summarizationModel = Objects.requireNonNull(summarizationModel, "Summarization model cannot be null");
        this.researchModel = Objects.requireNonNull(researchModel, "Research model cannot be null");
        this.compressionModel = Objects.requireNonNull(compressionModel, "Compression model cannot be null");
        this.finalReportModel = Objects.requireNonNull(finalReportModel, "Final report model cannot be null");
        this.searchApi = Objects.requireNonNull(searchApi, "Search API cannot be null");
        this.maxStructuredOutputRetries = Math.max(1, maxStructuredOutputRetries);
        this.allowClarification = allowClarification;
        this.maxConcurrentResearchUnits = Math.max(1, maxConcurrentResearchUnits);
        this.maxResearcherIterations = Math.max(1, maxResearcherIterations);
        this.maxReactToolCalls = Math.max(1, maxReactToolCalls);
        this.availableTools = Objects.requireNonNull(availableTools, "Available tools list cannot be null");
        this.mcpServerUrl = mcpServerUrl;
        this.mcpRequireAuth = mcpRequireAuth;
        
        logger.info("Configuration initialized with {} tools and {} max concurrent units", 
                   availableTools.size(), maxConcurrentResearchUnits);
    }

    private void validateConfiguration(String summarizationModel, String researchModel, String compressionModel,
                                     String finalReportModel, String searchApi, int maxStructuredOutputRetries,
                                     int maxConcurrentResearchUnits, int maxResearcherIterations, int maxReactToolCalls,
                                     List<String> availableTools, String mcpServerUrl) {
        
        if (maxStructuredOutputRetries < 1) {
            throw new IllegalArgumentException("maxStructuredOutputRetries must be at least 1");
        }
        if (maxConcurrentResearchUnits < 1) {
            throw new IllegalArgumentException("maxConcurrentResearchUnits must be at least 1");
        }
        if (maxResearcherIterations < 1) {
            throw new IllegalArgumentException("maxResearcherIterations must be at least 1");
        }
        if (maxReactToolCalls < 1) {
            throw new IllegalArgumentException("maxReactToolCalls must be at least 1");
        }
    }

    public static Configuration fromEnvironment() {
        String summarizationModel = getEnvOrDefault("SUMMARIZATION_MODEL", "kimi-k2-0711-preview");
        String researchModel = getEnvOrDefault("RESEARCH_MODEL", "kimi-k2-0711-preview");
        String compressionModel = getEnvOrDefault("COMPRESSION_MODEL", "kimi-k2-0711-preview");
        String finalReportModel = getEnvOrDefault("FINAL_REPORT_MODEL", "kimi-k2-0711-preview");
        String searchApi = getEnvOrDefault("SEARCH_API", "tavily");
        
        int maxRetries = getIntEnvOrDefault("MAX_STRUCTURED_OUTPUT_RETRIES", 3);
        boolean allowClarification = getBooleanEnvOrDefault("ALLOW_CLARIFICATION", false);
        int maxConcurrent = getIntEnvOrDefault("MAX_CONCURRENT_RESEARCH_UNITS", 3);
        int maxIterations = getIntEnvOrDefault("MAX_RESEARCHER_ITERATIONS", 5);
        int maxToolCalls = getIntEnvOrDefault("MAX_REACT_TOOL_CALLS", 5);
        
        String toolsStr = getEnvOrDefault("AVAILABLE_TOOLS", "tavily_search,arxiv_search");
        List<String> availableTools = List.of(toolsStr.split(","));
        
        String mcpServerUrl = System.getenv("MCP_SERVER_URL");
        boolean mcpRequireAuth = getBooleanEnvOrDefault("MCP_REQUIRE_AUTH", false);
        
        return new Configuration(summarizationModel, researchModel, compressionModel, finalReportModel,
                               searchApi, maxRetries, allowClarification, maxConcurrent, maxIterations,
                               maxToolCalls, availableTools, mcpServerUrl, mcpRequireAuth);
    }

    private static String getEnvOrDefault(String key, String defaultValue) {
        String value = System.getenv(key);
        return value != null && !value.trim().isEmpty() ? value : defaultValue;
    }

    private static int getIntEnvOrDefault(String key, int defaultValue) {
        String value = System.getenv(key);
        if (value != null && !value.trim().isEmpty()) {
            try {
                return Integer.parseInt(value.trim());
            } catch (NumberFormatException e) {
                logger.warn("Invalid integer value for {}: {}, using default: {}", key, value, defaultValue);
            }
        }
        return defaultValue;
    }

    private static boolean getBooleanEnvOrDefault(String key, boolean defaultValue) {
        String value = System.getenv(key);
        if (value != null && !value.trim().isEmpty()) {
            return Boolean.parseBoolean(value.trim());
        }
        return defaultValue;
    }

    // Getter methods
    public String getSummarizationModel() { return summarizationModel; }
    public String getResearchModel() { return researchModel; }
    public String getCompressionModel() { return compressionModel; }
    public String getFinalReportModel() { return finalReportModel; }
    public String getSearchApi() { return searchApi; }
    public int getMaxStructuredOutputRetries() { return maxStructuredOutputRetries; }
    public boolean isAllowClarification() { return allowClarification; }
    public int getMaxConcurrentResearchUnits() { return maxConcurrentResearchUnits; }
    public int getMaxResearcherIterations() { return maxResearcherIterations; }
    public int getMaxReactToolCalls() { return maxReactToolCalls; }
    public List<String> getAvailableTools() { return availableTools; }
    public String getMcpServerUrl() { return mcpServerUrl; }
    public boolean isMcpRequireAuth() { return mcpRequireAuth; }
}